The JSON.NET documentation has the following approach, that I would also suggest using:
First - deserialise to a sensible type (anonymous is fine)
var json = "{id: 12, data: 'my data'}";
var definition = new { Id = 0, Data = "" }
var deserialised = JsonConvert.DeserializeAnonymousType(json, definition);
Second - you've got your first item, so you can "trick" the compiler into letting you use the anonymous type in a list:
var history = (new[] { deserialised }).ToList();
You can then shove any other deserialised instances into that list.
Now you can do your filtering:
var itemImLookingFor = history.SingleOrDefault(x => x.Id == 10);
Once you've then got the item, you can just update it:
itemImLookingFor.Data = itemImLookingFor.Data.ToUpperCase()
I'd recommend reading this as it explains some of the shortcomings inherent in using the dynamic
keyword; it's not a bad thing to do, it just has its place.
For this scenario, JSON.NET gives you all the tools you need to either deserialise to a type of your own defining (e.g. write a class that mirrors the JSON, or to an anonymous type like I've done here).