Indeed, for types Foo<T> that have an indirection to the type T we want to update (otherwise no need for strong update), that are cheap to deconstruct and reconstruct (size_of::<Foo<T>>() is small), and store the type T in a way that only cares about layout, we can use strong update between Foo<MaybeUninit<T>> and Foo<T> to the cost of deconstructing and reconstructing (which may be optimized out).
However, I'm not convinced by the benefit. This permits to have init be a safe function. But to call it you need to provide the initializing closure, which needs to use unsafe because it will call assume_init_mut(). So it's not clear to me why prefer this compared to what we would do now:
/// Safety: f must initialize its argument
unsafe fn init(xs: Vec<MaybeUninit<T>>, f: impl FnMut(&mut MaybeUninit<T>)) -> Vec<T>