Gaffer on Games, an experienced authority on online multiplayer games, recommends having the clients show one or two ticks behind the server's state.
When the client receives state 100, for example, it starts interpolating from the state it already has (state 99) and state 100 such that it should reach state 100 at the same time that it receives state 101 from the server. The server sends state updates at a fixed rate, so this is predictable, but it does inherently introduce a small bit of extra latency (based on the update rate).
If you want to cover up the occasional lost packet, have the client show two states behind the server. For example, when it receives state 100 it starts interpolating from state 98 to 99, such that it should be showing state 99 when state 101 is received. If state 101 doesn't come through (due to a lost packet), it continues interpolating between 99 and 100, anticipating 102 to come through next. When state 102 comes through, it can interpolate between states 100 and 102 over two update cycles, and the player should be none the wiser. This, of course, doubles that extra latency, but with a high enough update rate, is not a problem.
Edit to better answer your question according to your comment. I've kept the previous part as it informs the example in the latter part:
Where you have network jitter, my suggestion is that when updates come later than expected (or two in a row do, if you use the two-cycle smoothing described above), they set the new expectation for latency. When packets come sooner than expected, instead of jumping ahead in time, store those states in a buffer and continue catching up at a consistent rate, assuming that packets may still come through with as much latency as your worst case thus far. Of course, you wouldn't want an unlucky spike in latency to add artificial lag to the rest of the session, so as packets continue to come in sooner than expected, slowly bring that simulation lag down to catch up with the server, perhaps with a buffer if the incoming states vary quite a bit in timing.
As an example, you might expect an update rate of 20 updates a second. That's an update every 50ms. If update 100 comes through slower than expected and you aren't using an extra update cycle of smoothing, you're forced to wait for it. But once it does come through, you interpolate between state 99 and 100 such that you should reach state 100 in 50ms. In that time, since you have all that network jitter, state 101 and 102 arrive. But instead of jumping ahead to them, you store them, consistently taking 50ms to move from one state to another. As you continue to sit a few states behind what you've received, you decide to play catch up and start moving from one state to another in only 49ms (or even less), subtly bringing the player forward in time to enjoy the improved latency their connection has been having without any abrupt changes in simulation speed.
In anticipation of further inconsistencies, you may want to remember the worst delay you've had in the last x number of seconds and stop catching up when you reach that delay again (that is, return to 50ms between each state of you're expecting 20 updates per second).
With a two cycle delay, you can ignore one-off delays, and need only remember the best of two consecutive delayed states in the last x seconds. It could be worth switching between a single cycle delay and two cycle delay depending on the quality of the connection.
I hope that's helpful, and if not, hopefully someone with experience in that area can correct me and teach us both!