This solution uses #2 (Session) since its simpler to code however this demonstrates the principles.
Views
Index View:
@using StackOverflow.Models
    <div>
    @{ Html.RenderPartial("PersonGrid", Model.Persons, new ViewDataDictionary()); }
    @Html.Partial("NewPerson", new Person())
    @{ Html.RenderPartial("ContactGrid", Model.Contacts, new ViewDataDictionary()); }
    @Html.Partial("NewContact", new Contact())
    @using(Html.BeginForm("Validate", "Home", FormMethod.Post))
    {
        <input type="submit" value="Validate" />
    }
    </div>
Person Grid
    @model IList
    <table>
        <thead>
            <tr>
                <td>First Name</td>
                <td>Last Name</td>
            </tr>
        </thead>
        <tbody>
            @if (Model != null && Model.Any())
            {
                foreach (var person in Model)
                {
                    <tr>
                        <td>@person.FirstName</td>
                        <td>@person.LastName</td>
                    </tr>
                }
            }
            else
            {
                <tr>
                    <td colspan="2" style="text-align: center">No persons available</td>
                </tr>
            }
        </tbody>
    </table>
Contact Grid
    @model IList
    <table>
        <thead>
            <tr>
                <td>Phone</td>
            </tr>
        </thead>
        <tbody>
            @if (Model != null && Model.Any())
            {
                foreach (var contact in Model)
                {
                    <tr>
                        <td>@contact.Phone</td>
                    </tr>
                }
            }
            else
            {
                <tr>
                    <td>No contacts available</td>
                </tr>
            }
        </tbody>
    </table>
New Person
    @model StackOverflow.Models.Person
    @using (Html.BeginForm("NewPerson", "Home", FormMethod.Post))
    {
        <div>
            @Html.Hidden("PersonViewState", TempData["PersonViewState"])
            @Html.LabelFor(m => m.FirstName)<br />
            @Html.TextBoxFor(m => m.FirstName)<br />
            <br />
            @Html.LabelFor(m => m.LastName)<br />
            @Html.TextBoxFor(m => m.LastName)<br />
            <br />
            <input type="submit" value="Submit" />
        </div>
    }
New Contact
    @model StackOverflow.Models.Contact
    @using (Html.BeginForm("NewContact", "Home", FormMethod.Post))
    {
        <div>
            @Html.LabelFor(m => m.Phone)<br />
            @Html.TextBoxFor(m => m.Phone)<br />
            <br />
            <input type="submit" value="Submit" />
        </div>
    }
Models
    public class Person
    {
        [Display(Name = "First Name")]
        public string FirstName { get; set; }
        [Display(Name = "Last Name")]
        public string LastName { get; set; }
    }
    public class Contact
    {
        [Display(Name = "Phone")]
        public string Phone { get; set; }
    }
    public class HomeModel
    {
        public IList<Person> Persons { get; set; }
        public IList<Contact> Contacts { get; set; }
    }
Helpers
    public static class PersistenceMechanism
    {
        public static IList GetPersons()
        {
            return (IList<Person>) HttpContext.Current.Session["__Persons"];
        }
        public static IList GetContacts()
        {
            return (IList<Contact>) HttpContext.Current.Session["__Contacts"];
        }
        public static void Update(IList<Person> persons)
        {
            HttpContext.Current.Session["__Persons"] = persons;
        }
        public static void Update(IList<Contact> contacts)
        {
            HttpContext.Current.Session["__Contacts"] = contacts;
        }
    }
Controller
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            var model = new HomeModel
                            {
                                Persons = PersistenceMechanism.GetPersons(),
                                Contacts = PersistenceMechanism.GetContacts()
                            };
            return View(model);
        }
        [HttpGet]
        public ActionResult PersonGrid()
        {
            var persons = PersistenceMechanism.GetPersons();
            return PartialView(persons);
        }
        [HttpGet]
        public ActionResult ContactGrid()
        {
            var contacts = PersistenceMechanism.GetContacts();
            return PartialView(contacts);
        }
        [HttpPost]
        public ActionResult NewPerson(Person model)
        {
            var persons = PersistenceMechanism.GetPersons() ?? new List<Person>();
            persons.Add(model);
            PersistenceMechanism.Update(persons);
            return RedirectToAction("Index");
        }
        [HttpPost]
        public ActionResult NewContact(Contact model)
        {
            var contacts = PersistenceMechanism.GetContacts() ?? new List<Contact>();
            contacts.Add(model);
            PersistenceMechanism.Update(contacts);
            return RedirectToAction("Index");
        }
        [HttpPost]
        public ActionResult Validate()
        {
            var persons = PersistenceMechanism.GetPersons();
            var contacts = PersistenceMechanism.GetContacts();
            // validate
            // ...
            return RedirectToAction("Index");
        }
    }