It looks like I needed to mark the array as modified again immediately before the populate. I guess Mongoose fetches the old array out of the database for the populate otherwise? That doesn't make much sense since the populate is done in the save callback. Not sure but it is working with that change.
gamestate2.markModified('unusedTiles');