Maybe doing it like this would be better:
update({id, array has old_item, array doesn't have new_item},{$set old item to new item})
update({id, array has old_item and new_item},{$pull old_item})
it's still two updates, but the difference is that only one would actually change the document, so the other would be very fast since it wouldn't do anything. Actually you could detect if the first one does update a record and not bother running the second if it does, but you could also just run these fire and forget if you don't care to wait.
so your code would look like:
> db.a.remove()
> db.a.insert({_id:0,field:["one_value","old_value","old_value2","another_value"]})
> db.a.find()
{ "_id" : 0, "field" : [ "one_value", "old_value", "old_value2", "another_value" ] }
> db.a.update({_id:0,field:{$in:["old_value"],$ne:"new_value"}},{$set:{"field.$":"new_value"}})
> db.a.update({_id:0,field:{$in:["old_value","new_value"]}}, {$pull:{field:"old_value"}})
> db.a.find()
{ "_id" : 0, "field" : [ "one_value", "new_value", "old_value2", "another_value" ] }
> db.a.update({_id:0,field:{$in:["old_value2"],$ne:"new_value"}},{$set:{"field.$":"new_value"}})
> db.a.update({_id:0,field:{$in:["old_value2","new_value"]}}, {$pull:{field:"old_value2"}})
> db.a.find()
{ "_id" : 0, "field" : [ "one_value", "new_value", "another_value" ] }
>
but this approach doesn't add new_value if it's not already in the list, so it depends if you want that too (I'm not sure I can see why you would want to add a tag and optionally replace an existing tag in the same operation in a tagging use case)