Should there be a check here on `f`?  For example consider the input `solve_univariate(cos(x**2) - 1, x)`.  This correctly raises a `NotImplementeError` but it does so from within `solve_as_poly`.  Probably it should err sooner.