Hi Daniel,
I came across this one myself (using Stripe as the payment processor) and the only way to make this user-friendly (money-wise) is to write some custom code just as Pat suggested.
But remember that this can create some unwanted scenarios:
Suppose you offer two membership levels with no trial period. The levels are charged for $10 (level1) and $20 (level2) per month.
A user signs up for a level 1 membership and he is charged $10 for his first month. A day later he upgrades to level 2 for $20 per month.
If you write some custom code, as suggested by Pat, to make this upgrade happen and give him a 29 day trial period (so the billing cycle stays the same as when he signed up for level 1), this user in fact gets his (almost) first month of level 2 with a 50% discount.
This doesn’t sound fair to other paid users. So you might want to reconsider the option Pat provided.
Another solution could be that upgrading to a higher level can only occur 1 day before the current billing cycle. But you will have to write some custom code for this to happen as well.